/**
 * Copyright (c) 2018-2024, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 * 
 * Contains: Device tree example driver
 * 
 * Change Logs:
 * Date           Author            Notes
 * 2024-1-4       JasonHu           Init
 */

#include <base/driver.h>

#ifdef CONFIG_NX_DRIVER_DTREE

#define NX_LOG_NAME "tree"
#include <base/log.h>
#include <base/memory.h>
#include <base/string.h>
#include <base/malloc.h>

#define DRV_NAME "tree driver"
#define DEV_NAME "tree"

NX_PRIVATE NX_DriverOps TreeDriverOps = {
    .read = NX_NULL,
    .write = NX_NULL,
};

NX_PRIVATE int devidx = 0;

NX_PRIVATE NX_Device *TreeProbe(NX_Driver *driver, DT_Node *node)
{
    NX_Device *device;
    int i, n;
    char name[32] = {0};

    NX_SNPrintf(name, 32,"%s%d",node->name, devidx++);

    if (NX_DriverAttachDevice(driver, name, &device) != NX_EOK)
    {
        NX_LOG_E("attach device error\n");
        return NX_NULL;
    }

    /* get node info */
    if (!DT_ReadBool(node, "isarray", 0))
    {
        NX_Printf("bool_false: %d\n", DT_ReadBool(node, "bool_false", 0));
        NX_Printf("bool_true: %d\n", DT_ReadBool(node, "bool_true", 0));
        NX_Printf("int_half: %d\n", DT_ReadInt(node, "int_half", 0));
        NX_Printf("int_max: %u\n", DT_ReadInt(node, "int_max", 0));
        NX_Printf("long_half: %p\n", DT_ReadLong(node, "long_half", 0));
        NX_Printf("long_max: %p\n", DT_ReadLong(node, "long_max", 0));
        NX_Printf("str_null: %s\n", DT_ReadString(node, "str_null", "none"));
        NX_Printf("str_hello: %s\n", DT_ReadString(node, "str_hello", "none"));
        NX_Printf("str_clang: %s\n", DT_ReadString(node, "str_clang", "none"));
        NX_Printf("u8_max: %x\n", DT_ReadU8(node, "u8_max", 0));
        NX_Printf("u16_max: %x\n", DT_ReadU16(node, "u16_max", 0));
        NX_Printf("u32_max: %x\n", DT_ReadU32(node, "u32_max", 0));
        NX_Printf("u64_max: %p\n", DT_ReadU32(node, "u64_max", 0));
    }
    else
    {
        n = DT_ReadArrayLength(node, "bool");
        for (i = 0; i < n; i++)
            NX_Printf("bool: %d\n", DT_ReadArrayBool(node, "bool", i, 0));

        n = DT_ReadArrayLength(node, "int");
        for (i = 0; i < n; i++)
            NX_Printf("int: %u\n", DT_ReadArrayInt(node, "int", i, 0));
        
        n = DT_ReadArrayLength(node, "long");
        for (i = 0; i < n; i++)
            NX_Printf("long: %p\n", DT_ReadArrayLong(node, "long", i, 0));

        n = DT_ReadArrayLength(node, "str");
        for (i = 0; i < n; i++)
            NX_Printf("str: %s\n", DT_ReadArrayString(node, "str", i, "none"));
        
        n = DT_ReadArrayLength(node, "u8");
        for (i = 0; i < n; i++)
            NX_Printf("u8: %x\n", DT_ReadArrayU8(node, "u8", i, 0));
            
        n = DT_ReadArrayLength(node, "u16");
        for (i = 0; i < n; i++)
            NX_Printf("u16: %x\n", DT_ReadArrayU16(node, "u16", i, 0));
            
        n = DT_ReadArrayLength(node, "u32");
        for (i = 0; i < n; i++)
            NX_Printf("u32: %x\n", DT_ReadArrayU32(node, "u32", i, 0));
            
        n = DT_ReadArrayLength(node, "u64");
        for (i = 0; i < n; i++)
            NX_Printf("u64: %p\n", DT_ReadArrayU32(node, "u64", i, 0));
    }
    return device;
}

NX_PRIVATE NX_Error TreeRemove(NX_Device *device)
{
    return NX_EOK;
}

NX_PRIVATE const NX_DeviceId TreeIdTable[] = {
    {"dummy,node",},
    {"dummy,node-array",},
    {},
};

NX_PRIVATE void TreeDriverInit(void)
{
    NX_Driver *driver = NX_DriverCreate(DRV_NAME, NX_DEVICE_TYPE_VIRT, 0, &TreeDriverOps);
    if (driver == NX_NULL)
    {
        NX_LOG_E("create driver failed!");
        return;
    }

    driver->probe = TreeProbe;
    driver->remove = TreeRemove;
    driver->idTable = TreeIdTable;

    if (NX_DriverRegister(driver) != NX_EOK)
    {
        NX_LOG_E("register driver %s failed!", DRV_NAME);
        NX_DriverDetachDevice(driver, DEV_NAME);
        NX_DriverDestroy(driver);
        return;
    }
    
    NX_LOG_I("init %s driver success!", DRV_NAME);
}

NX_PRIVATE void TreeDriverExit(void)
{
    NX_DriverCleanup(DRV_NAME);
}

NX_DRV_INIT(TreeDriverInit);
NX_DRV_EXIT(TreeDriverExit);

#endif
